#include "dm_protocol.h"
#include "log.h"


namespace secsmart_protocol
{
    DETECT_RESULT DMProtocol::parse(secsmart_session::session_sptr session, const uint8_t *buf, size_t size, bool is_forward)
    {
        direction = secsmart_session::session_dirction_t::SESSION_DIRCTION_UNKNOW;
        if(size < DM_PACKET_HEAD_LEN + DM_BODY_HEAD_LEN) //小于协议头
        {
            return DETECT_RESULT::DETECT_UNKNOWN;
        }
        int16_t cmdType = (int16_t)(((buf[5] & 0xFF) << 8) | (buf[4] & 0xFF));
        if(!isTrueCmd(cmdType))
        {
            return DETECT_RESULT::DETECT_UNKNOWN;  //可能存在TCP分段的情况
        }
        uint64_t pBodyLen = (uint32_t)(((buf[9] & 0xFF) << 24) | ((buf[8] & 0xFF) << 16) | ((buf[7] & 0xFF) << 8) | (buf[6] & 0xFF));
        if(pBodyLen + DM_BODY_HEAD_LEN + DM_PACKET_HEAD_LEN == size)
        {
            if(!setIpPort(session,getDirction(),is_forward))
            {
                LOG_DEBUG("Set ip port fail !");
                return DETECT_RESULT::DETECT_FAIL;
            }
            if(cmdType == DM7RSPTYPE::DM7_RSP_STARTUP)
            {
                size_t position = 64;
                parseVersion(buf,position,size);
            }
            addMatchCount();
            return DETECT_RESULT::DETECT_OK;
        }
        else 
        {
            return DETECT_RESULT::DETECT_UNKNOWN;
        }

    }

    bool DMProtocol::isTrueCmd(int16_t cmdType)
    {
        switch(cmdType)
        {
            case DM7REQCMD::DM7_CMD_LOGIN:
            case DM7REQCMD::DM7_CMD_LOGOUT:
            case DM7REQCMD::DM7_CMD_STMT_ALLOCATE:
            case DM7REQCMD::DM7_CMD_STMT_FREE:
            case DM7REQCMD::DM7_CMD_PREPARE:
            case DM7REQCMD::DM7_CMD_EXECUTE:
            case DM7REQCMD::DM7_CMD_FETCH:
            case DM7REQCMD::DM7_CMD_COMMIT:
            case DM7REQCMD::DM7_CMD_ROLLBACK:
            case DM7REQCMD::DM7_CMD_EXECUTE2:
            case DM7REQCMD::DM7_CMD_PUT_DATA:
            case DM7REQCMD::DM7_CMD_GET_DATA:
            case DM7REQCMD::DM7_CMD_STMT_CLOSE:
            case DM7REQCMD::DM7_CMD_EXPLAIN:
            case DM7REQCMD::DM7_CMD_CURSOR_SET_NAME:
            case DM7REQCMD::DM7_CMD_GET_LOB_LEN:
            case DM7REQCMD::DM7_CMD_SET_LOB_DATA:
            case DM7REQCMD::DM7_CMD_LOB_TRUNCATE:
            case DM7REQCMD::DM7_CMD_GET_LOB_DATA:
            case DM7REQCMD::DM7_CMD_MORE_RESULT:
            case DM7REQCMD::DM7_CMD_SESS_ISO:
            case DM7REQCMD::DM7_CMD_PRE_EXEC:
            case DM7REQCMD::DM7_CMD_EXEC_DIRECT:
            case DM7REQCMD::DM7_CMD_TABLE_TS:
            case DM7REQCMD::DM7_CMD_STARTUP:
            case DM7REQCMD::DM7_CMD_XA:
            {
                LOG_DEBUG("DM Request packet detected !");
                direction = secsmart_session::session_dirction_t::SESSION_DIRCTION_REQUEST;
                return true;
            }
            case DM7RSPTYPE::DM7_RSP_OTHER: // 0x00,绑定变量,部分命令语句的应答,此时statementid为0
            case DM7RSPTYPE::DM7_RSP_BASE: // 0x7F
            case DM7RSPTYPE::DM7_RSP_DDL_CDB: // 0x80
            case DM7RSPTYPE::DM7_RSP_DDL_CTAB: // 0x81
            case DM7RSPTYPE::DM7_RSP_DDL_DTAB: // 0x82
            case DM7RSPTYPE::DM7_RSP_DDL_CVIEW: // 0x83
            case DM7RSPTYPE::DM7_RSP_DDL_DVIEW: // 0x84
            case DM7RSPTYPE::DM7_RSP_DDL_CIND: // 0x85
            case DM7RSPTYPE::DM7_RSP_DDL_DIND: // 0x86
            case DM7RSPTYPE::DM7_RSP_DDL_CUSR: // 0x87
            case DM7RSPTYPE::DM7_RSP_DDL_DUSR: // 0x88
            case DM7RSPTYPE::DM7_RSP_DDL_CROL: // 0x89
            case DM7RSPTYPE::DM7_RSP_DDL_DROL: // 0x8A
            case DM7RSPTYPE::DM7_RSP_DDL_DROP: // 0x8B
            case DM7RSPTYPE::DM7_RSP_DDL_ALTDB: // 0x8C
            case DM7RSPTYPE::DM7_RSP_DDL_ALTUSR: // 0x8D
            case DM7RSPTYPE::DM7_RSP_DDL_CFUNC: // 0x8E
            case DM7RSPTYPE::DM7_RSP_DDL_CPROC: // 0x8F
            case DM7RSPTYPE::DM7_RSP_DDL_GRANT: // 0x90
            case DM7RSPTYPE::DM7_RSP_DDL_REVOKE: // 0x91
            case DM7RSPTYPE::DM7_RSP_DDL_ALTTAB: // 0x92
            case DM7RSPTYPE::DM7_RSP_COMMIT: // 0x93
            case DM7RSPTYPE::DM7_RSP_ROLLBACK: // 0x94
            case DM7RSPTYPE::DM7_RSP_EXPLAIN: // 0x95
            case DM7RSPTYPE::DM7_RSP_SET_TRAN: // 0x96
            case DM7RSPTYPE::DM7_RSP_SAVEPNT: // 0x97
            case DM7RSPTYPE::DM7_RSP_SET_CURDB: // 0x98
            case DM7RSPTYPE::DM7_RSP_SET_CURSCH: // 0x99
            case DM7RSPTYPE::DM7_RSP_LOCK_TAB: // 0x9A
            case DM7RSPTYPE::DM7_RSP_DDL_AUDIT: // 0x9B
            case DM7RSPTYPE::DM7_RSP_DML_INSERT: // 0x9D
            case DM7RSPTYPE::DM7_RSP_DML_DELETE: // 0x9E
            case DM7RSPTYPE::DM7_RSP_DML_UPDATE: // 0x9F
            case DM7RSPTYPE::DM7_RSP_DML_SELECT: // 0xA0
            case DM7RSPTYPE::DM7_RSP_DML_SELECT_INTO: // 0xA1
            case DM7RSPTYPE::DM7_RSP_DML_CALL: // 0xA2
            case DM7RSPTYPE::DM7_RSP_LOGIN: // 0xA3
            case DM7RSPTYPE::DM7_RSP_SET_TIME_ZONE: // 0xA5
            case DM7RSPTYPE::DM7_RSP_SET_SESS_TRAN: // 0xA6
            case DM7RSPTYPE::DM7_RSP_FETCH_NOT_OVER: // 0xA7
            case DM7RSPTYPE::DM7_RSP_EXEC_PROC: // 0xB2
            case DM7RSPTYPE::DM7_RSP_SIMPLE: // 0xBB
            case DM7RSPTYPE::DM7_RSP_DDL_CSCHEMA: // 0xBC
            case DM7RSPTYPE::DM7_RSP_PLAN_ERRCODE: // 0xBD
            case DM7RSPTYPE::DM7_RSP_DDL_ALTTRIG: // 0xBE
            case DM7RSPTYPE::DM7_RSP_DDL_DROP_TABLE: // 0xBF
            case DM7RSPTYPE::DM7_RSP_DDL_DROP_INDEX: // 0xC0
            case DM7RSPTYPE::DM7_RSP_DDL_DROP_VIEW: // 0xC1
            case DM7RSPTYPE::DM7_RSP_DML_TRCT: // 0xC2
            case DM7RSPTYPE::DM7_RSP_SET_IDENTINS: // 0xC3
            case DM7RSPTYPE::DM7_RSP_DDL_CSEQ: // 0xC4
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_DECLARE: // 0xC5
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_OPEN: // 0xC6
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_CLOSE: // 0xC7
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_DELETE: // 0xC9
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_FETCH: // 0xCA
            case DM7RSPTYPE::DM7_RSP_DML_CURSOR_SEEK: // 0xCB
            case DM7RSPTYPE::DM7_RSP_DDL_CLGN: // 0xCC
            case DM7RSPTYPE::DM7_RSP_DDL_ALTLGN: // 0xCD
            case DM7RSPTYPE::DM7_RSP_DDL_CCONIND: // 0xCE
            case DM7RSPTYPE::DM7_RSP_DDL_DCONIND: // 0xCF
            case DM7RSPTYPE::DM7_RSP_DDL_ALTCONIND: // 0xD0
            case DM7RSPTYPE::DM7_RSP_STARTUP: // 0xE4
            {
                LOG_DEBUG("DM Response packet detected !");
                direction = secsmart_session::session_dirction_t::SESSION_DIRCTION_RESPONSE;
                return true;
            }
            default:
            {
                return false;
            }
        }
    }

    void DMProtocol::parseVersion(const uint8_t *buf,size_t &position, size_t size)
    {
        skipBytesWithLen4(buf,position,size);
        skipBytesWithLen4(buf,position,size);
        skipBytesWithLen4(buf,position,size);
        skipBytesWithLen4(buf,position,size);
        versionInfo.clear();
        readBytesWithLen4(buf,position,size,versionInfo);
        if(isValidVersion(versionInfo))
        {
            version = versionInfo;
        }
    }

    bool DMProtocol::isValidVersion(const std::string &str)
    {
        //对版本号做简单的合法性校验
        if(str.empty())
        {
            return false;
        }
        // Check if the first and last characters are digits
        if(!std::isdigit(str.front()) || !std::isdigit(str.back()))
        {
            return false;
        }
        // Check if the string contains only digits and '.'
        for (char c : str) 
        {
            if (!std::isdigit(c) && c != '.') 
            {
                return false;
            }
        }
        return true;
    }

    std::string DMProtocol::extendInfo()
    {
        return "";
    }

   
}